{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2.1.0\n",
      "sys.version_info(major=3, minor=6, micro=9, releaselevel='final', serial=0)\n",
      "matplotlib 3.1.3\n",
      "numpy 1.18.1\n",
      "pandas 1.0.1\n",
      "sklearn 0.22.1\n",
      "tensorflow 2.1.0\n",
      "tensorflow_core.python.keras.api._v2.keras 2.2.4-tf\n"
     ]
    }
   ],
   "source": [
    "import matplotlib as mpl\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "import numpy as np\n",
    "import sklearn\n",
    "import pandas as pd\n",
    "import os\n",
    "import sys\n",
    "import time\n",
    "import tensorflow as tf\n",
    "\n",
    "from tensorflow import keras\n",
    "\n",
    "print(tf.__version__)\n",
    "print(sys.version_info)\n",
    "for module in mpl, np, pd, sklearn, tf, keras:\n",
    "    print(module.__name__, module.__version__)\n",
    "\n",
    "'''\n",
    "模型callbacks\n",
    "'''"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(5000, 28, 28) (5000,)\n",
      "(55000, 28, 28) (55000,)\n",
      "(10000, 28, 28) (10000,)\n"
     ]
    }
   ],
   "source": [
    "## 获取 数据函数\n",
    "fashion_mnist = keras.datasets.fashion_mnist\n",
    "## 调用该函数产生数据，和房价预测不同，他已经把训练集 和 测试集 分开了，返回两个tuple\n",
    "## 数据都是使用numpy.array来存储的\n",
    "(x_train_all, y_train_all), (x_test, y_test) = fashion_mnist.load_data()\n",
    "x_valid, x_train = x_train_all[:5000], x_train_all[5000:]\n",
    "y_valid, y_train = y_train_all[:5000], y_train_all[5000:]\n",
    "\n",
    "print(x_valid.shape, y_valid.shape)\n",
    "print(x_train.shape, y_train.shape)\n",
    "print(x_test.shape, y_test.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[[1 2 3 4 5 6]\n",
      "  [1 2 3 4 5 6]\n",
      "  [1 2 3 4 5 6]\n",
      "  [1 2 3 4 5 6]\n",
      "  [1 2 3 4 5 6]\n",
      "  [1 2 3 4 5 6]]\n",
      "\n",
      " [[1 2 3 4 5 6]\n",
      "  [1 2 3 4 5 6]\n",
      "  [1 2 3 4 5 6]\n",
      "  [1 2 3 4 5 6]\n",
      "  [1 2 3 4 5 6]\n",
      "  [1 2 3 4 5 6]]\n",
      "\n",
      " [[1 2 3 4 5 6]\n",
      "  [1 2 3 4 5 6]\n",
      "  [1 2 3 4 5 6]\n",
      "  [1 2 3 4 5 6]\n",
      "  [1 2 3 4 5 6]\n",
      "  [1 2 3 4 5 6]]\n",
      "\n",
      " [[1 2 3 4 5 6]\n",
      "  [1 2 3 4 5 6]\n",
      "  [1 2 3 4 5 6]\n",
      "  [1 2 3 4 5 6]\n",
      "  [1 2 3 4 5 6]\n",
      "  [1 2 3 4 5 6]]\n",
      "\n",
      " [[1 2 3 4 5 6]\n",
      "  [1 2 3 4 5 6]\n",
      "  [1 2 3 4 5 6]\n",
      "  [1 2 3 4 5 6]\n",
      "  [1 2 3 4 5 6]\n",
      "  [1 2 3 4 5 6]]\n",
      "\n",
      " [[1 2 3 4 5 6]\n",
      "  [1 2 3 4 5 6]\n",
      "  [1 2 3 4 5 6]\n",
      "  [1 2 3 4 5 6]\n",
      "  [1 2 3 4 5 6]\n",
      "  [1 2 3 4 5 6]]]\n"
     ]
    }
   ],
   "source": [
    "data=np.array([\n",
    "    [\n",
    "        [1,2,3,4,5,6],\n",
    "        [1,2,3,4,5,6],\n",
    "        [1,2,3,4,5,6],\n",
    "        [1,2,3,4,5,6],\n",
    "        [1,2,3,4,5,6],\n",
    "        [1,2,3,4,5,6],\n",
    "    ],\n",
    "    [\n",
    "        [1,2,3,4,5,6],\n",
    "        [1,2,3,4,5,6],\n",
    "        [1,2,3,4,5,6],\n",
    "        [1,2,3,4,5,6],\n",
    "        [1,2,3,4,5,6],\n",
    "        [1,2,3,4,5,6],\n",
    "    ],\n",
    "    [\n",
    "        [1,2,3,4,5,6],\n",
    "        [1,2,3,4,5,6],\n",
    "        [1,2,3,4,5,6],\n",
    "        [1,2,3,4,5,6],\n",
    "        [1,2,3,4,5,6],\n",
    "        [1,2,3,4,5,6],\n",
    "    ],\n",
    "    [\n",
    "        [1,2,3,4,5,6],\n",
    "        [1,2,3,4,5,6],\n",
    "        [1,2,3,4,5,6],\n",
    "        [1,2,3,4,5,6],\n",
    "        [1,2,3,4,5,6],\n",
    "        [1,2,3,4,5,6],\n",
    "    ],\n",
    "    [\n",
    "        [1,2,3,4,5,6],\n",
    "        [1,2,3,4,5,6],\n",
    "        [1,2,3,4,5,6],\n",
    "        [1,2,3,4,5,6],\n",
    "        [1,2,3,4,5,6],\n",
    "        [1,2,3,4,5,6],\n",
    "    ],\n",
    "    [\n",
    "        [1,2,3,4,5,6],\n",
    "        [1,2,3,4,5,6],\n",
    "        [1,2,3,4,5,6],\n",
    "        [1,2,3,4,5,6],\n",
    "        [1,2,3,4,5,6],\n",
    "        [1,2,3,4,5,6],\n",
    "    ]\n",
    "])\n",
    "\n",
    "data2=data.reshape(-1,1)\n",
    "print(data2.reshape(-1,6,6))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# x = (x - u) / std\n",
    "## 归一化操作\n",
    "from sklearn.preprocessing import StandardScaler\n",
    "\n",
    "scaler = StandardScaler()\n",
    "# x_train: [None, 28, 28] -> [None*784, 1]\n",
    "x_train_scaled = scaler.fit_transform(\n",
    "    ## reshape() 函数，将数据从三维转换为二维（函数要求输入的数据是二维），且最小维度上的数据长度为1\n",
    "    ## 再调用reshape，将归一化好的数据reshape回来\n",
    "    ## 一个数据被reshape成(-1,1)的格式，也能在被reshape()回来，即这个过程是可逆的\n",
    "    x_train.astype(np.float32).reshape(-1, 1)).reshape(-1, 28, 28)\n",
    "x_valid_scaled = scaler.transform(\n",
    "    x_valid.astype(np.float32).reshape(-1, 1)).reshape(-1, 28, 28)\n",
    "x_test_scaled = scaler.transform(\n",
    "    x_test.astype(np.float32).reshape(-1, 1)).reshape(-1, 28, 28)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model: \"sequential_3\"\n",
      "_________________________________________________________________\n",
      "Layer (type)                 Output Shape              Param #   \n",
      "=================================================================\n",
      "flatten_3 (Flatten)          (None, 784)               0         \n",
      "_________________________________________________________________\n",
      "dense_6 (Dense)              (None, 20)                15700     \n",
      "_________________________________________________________________\n",
      "dense_7 (Dense)              (None, 10)                210       \n",
      "=================================================================\n",
      "Total params: 15,910\n",
      "Trainable params: 15,910\n",
      "Non-trainable params: 0\n",
      "_________________________________________________________________\n"
     ]
    }
   ],
   "source": [
    "# tf.keras.models.Sequential()\n",
    "\n",
    "\"\"\"\n",
    "model = keras.models.Sequential()\n",
    "model.add(keras.layers.Flatten(input_shape=[28, 28]))\n",
    "model.add(keras.layers.Dense(300, activation=\"relu\"))\n",
    "model.add(keras.layers.Dense(100, activation=\"relu\"))\n",
    "model.add(keras.layers.Dense(10, activation=\"softmax\"))\n",
    "\"\"\"\n",
    "\n",
    "model = keras.models.Sequential([\n",
    "    ## 模型需要将数据展平\n",
    "    ## 需要注意的是：flatten本身是没有input_shape这个参数的，他的功能仅仅是将输入数据转换为二维矩阵，保留batch_size的信息（最外层信息）\n",
    "    ## 但是他是继承自layer，放在模型的第一个位置，就要使用声明input_shape，--Retrieves（检索） the input shape(s) of a layer.\n",
    "    \n",
    "    ## 转入input_shape，确认模型结构\n",
    "    keras.layers.Flatten(input_shape=[28, 28]),\n",
    "    \n",
    "#     keras.layers.Dense(300, activation='relu'),\n",
    "#     keras.layers.Dense(100, activation='relu'),\n",
    "     keras.layers.Dense(20, activation='relu'),\n",
    "    keras.layers.Dense(10, activation='softmax')\n",
    "])\n",
    "\n",
    "# relu: y = max(0, x)\n",
    "# softmax: 将向量变成概率分布. x = [x1, x2, x3], \n",
    "#          y = [e^x1/sum, e^x2/sum, e^x3/sum], sum = e^x1 + e^x2 + e^x3\n",
    "\n",
    "# reason for sparse: y->index. y->one_hot->[] \n",
    "model.compile(loss=\"sparse_categorical_crossentropy\",\n",
    "              optimizer = \"sgd\",\n",
    "              metrics = [\"accuracy\"])\n",
    "\n",
    "## 上面传入input_shape 确认模型结构之后，这里才能使用summary()函数查看模型结构\n",
    "model.summary()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train on 55000 samples, validate on 5000 samples\n",
      "Epoch 1/10\n",
      "55000/55000 [==============================] - 3s 50us/sample - loss: 0.6191 - accuracy: 0.7821 - val_loss: 0.4738 - val_accuracy: 0.8344\n",
      "Epoch 2/10\n",
      "55000/55000 [==============================] - 2s 42us/sample - loss: 0.4540 - accuracy: 0.8381 - val_loss: 0.4321 - val_accuracy: 0.8450\n",
      "Epoch 3/10\n",
      "55000/55000 [==============================] - 2s 42us/sample - loss: 0.4215 - accuracy: 0.8503 - val_loss: 0.3965 - val_accuracy: 0.8626\n",
      "Epoch 4/10\n",
      "55000/55000 [==============================] - 2s 43us/sample - loss: 0.4018 - accuracy: 0.8573 - val_loss: 0.4111 - val_accuracy: 0.8540\n",
      "Epoch 5/10\n",
      "55000/55000 [==============================] - 2s 42us/sample - loss: 0.3879 - accuracy: 0.8634 - val_loss: 0.3819 - val_accuracy: 0.8634\n",
      "Epoch 6/10\n",
      "55000/55000 [==============================] - 2s 41us/sample - loss: 0.3772 - accuracy: 0.8663 - val_loss: 0.3688 - val_accuracy: 0.8710\n",
      "Epoch 7/10\n",
      "55000/55000 [==============================] - 2s 42us/sample - loss: 0.3674 - accuracy: 0.8695 - val_loss: 0.3709 - val_accuracy: 0.8650\n",
      "Epoch 8/10\n",
      "55000/55000 [==============================] - 2s 42us/sample - loss: 0.3601 - accuracy: 0.8722 - val_loss: 0.3645 - val_accuracy: 0.8708\n",
      "Epoch 9/10\n",
      "55000/55000 [==============================] - 2s 41us/sample - loss: 0.3535 - accuracy: 0.8743 - val_loss: 0.3642 - val_accuracy: 0.8688\n",
      "Epoch 10/10\n",
      "55000/55000 [==============================] - 2s 41us/sample - loss: 0.3477 - accuracy: 0.8764 - val_loss: 0.3686 - val_accuracy: 0.8700\n"
     ]
    }
   ],
   "source": [
    "# Tensorboard, earlystopping, ModelCheckpoint\n",
    "\n",
    "## 指定callbacks\n",
    "logdir = './callbacks'\n",
    "if not os.path.exists(logdir):\n",
    "    os.mkdir(logdir)\n",
    "output_model_file = os.path.join(logdir,\n",
    "                                 \"fashion_mnist_model.h5\")\n",
    "\n",
    "callbacks = [\n",
    "    ## 查看模型训练结构\n",
    "    keras.callbacks.TensorBoard(logdir),\n",
    "    ## 存储训练过程中最好效果的模型结构，这个是keras自带的模型保存格式  .h5文件格式\n",
    "    keras.callbacks.ModelCheckpoint(output_model_file,\n",
    "                                    save_best_only = True),\n",
    "    ## 提早停止训练\n",
    "    keras.callbacks.EarlyStopping(patience=5, min_delta=1e-3),\n",
    "]\n",
    "history = model.fit(x_train_scaled, y_train, epochs=5,\n",
    "                    validation_data=(x_valid_scaled, y_valid))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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UpcCPwcu0lo7OqZ6QgghRO/TnmvOa4AhSqlspZQFuAV4L7iAUmo08AJwjda6uOOrKYQQQvQepwxnrbUbuA9YDGwD5mmttyilfqOUusZfbDYQDfxTKbVeKfVeG7sTQgghxCm065qz1noRsKjZul8GzV/awfXq8dxuNyaTjAEjhBCiJRm+sxXXXnstY8eOZfjw4cyZMweA//znP4wZM4aCggIuueQSwHf34D333EN+fj4jR45kwYIFAE3uKJw/fz7Tp08HYPr06cycOZOzzz6bBx98kC+++IJzzz2X0aNHc95557Fjxw7Ad/f0j3/8Y0aMGMHIkSN55plnWLp0Kddee21gvx9//DHXXXddV/w4hBBCdLHw7bp9+BAc29Sx+0zLhymPn7LYK6+8QmJiIvX19YwbN46pU6dy1113sWLFCrKzsykrKwPgt7/9LbGxsWza5KtneXn5KfddVFTEypUrMRqNVFVV8cknn2AymViyZAkPP/wwCxYsYM6cOezfv5/169djMpkoKysjISGBe++9l5KSElJSUvjb3/7GHXfc8fV+HkIIIcJS+IZzCP35z39m4cKFABw6dIg5c+Zw4YUXkp2dDUBiYiIAS5Ys4aWXXgp8LyEh4ZT7vummmwLPFFdWVnL77beza9culFK4XK7AfmfOnBk47d1wvG9961u88cYbzJgxg1WrVvHaa691UIuFEEKEk/AN53b0cDvD8uXLWbJkCatWrSIyMpLCwkJGjRrF9u3b270PpVRg3m63N9kWFRUVmH/kkUeYOHEiCxcuZP/+/ad8hm/GjBlcffXV2Gw2brrpJrlmLYQQPZRcc26msrKShIQEIiMj2b59O6tXr8Zut7NixQr27dsHEDitfdlll/Hiiy8GvttwWrtPnz5s27YNr9cb6IG3dayMjAwA5s6dG1h/2WWX8cILL+B2u5scLz09nfT0dGbNmsWMGTM6rtFCCCHCioRzM5MnT8btdjN06FAeeughzjnnHFJSUpgzZw7XX389BQUFTJs2DYBf/OIXVFRUMGLECAoKCli2bBkAjz/+OFdddRXnnXceffv2bfNYDz74ID/72c8YPXp0IIgB7rzzTvr168fIkSMpKCjgrbfeCmy77bbbyMrKYujQoZ30ExBCCBFqcl60GavVyocfftjqtilTpjRZjo6O5oUXXmgx9OWNN97IjTfe2OL7wb1jgHPPPZedO3cGlmfN8g1HbjKZePrpp3n66adb7OPTTz/lrrvualdbhBBCdE8Szt3I2LFjiYqK4qmnngp1VYQQQnQiCeduZN26daGughBCiC4g15yFEEKIMCPhLIQQQoQZCWchhBAizEg4CyGEEGFGwlkIIYQIMxLOX0Pw26ea279/PyNGjOjC2gghhOgpJJyFEEKIMBO2zzn//ovfs72s/S+baI+8xDx+Ov6nbW5/6KGHyMrK4rvf/S4Av/71rzGZTCxbtozy8nJcLhezZs1i6tSpp3Vcu93OPffcw9q1awOjf02cOJEtW7YwY8YMnE4nXq+XBQsWkJ6ezs0330xRUREej4dHHnkkMFyoEEKI3iFswzkUpk2bxve///1AOM+bN4/FixfzwAMPEBsbS2lpKeeccw7XXHNNkzdPncqzzz6LUopNmzaxfft2Jk2axM6dO3n++ef53ve+x2233YbT6cTj8bBo0SLS09P54IMPAN/LMYQQQvQuYRvOJ+vhdpbRo0dTXFzMkSNHKCkpISEhgbS0NH7wgx+wYsUKDAYDhw8f5vjx46SlpbV7v59++in3338/AHl5efTv35+dO3dy7rnn8uijj1JUVMT111/PkCFDyM/P50c/+hE//elPueqqq5gwYUJnNVcIIUSYkmvOzdx0003Mnz+ft99+m2nTpvHmm29SUlLCunXrWL9+PX369GnxjuYz9Y1vfIP33nuPiIgIrrjiCpYuXUpOTg5ffvkl+fn5/OIXv+A3v/lNhxxLCCFE9xG2PedQmTZtGnfddRelpaX873//Y968eaSmpmI2m1m2bBkHDhw47X1OmDCBN998k4svvpidO3dy8OBBcnNz2bt3LwMHDuSBBx7g4MGDbNy4kby8PBITE/nmN79JfHw8L730Uie0UgghRDiTcG5m+PDhVFdXk5GRQd++fbntttu4+uqryc/P56yzziIvL++093nvvfdyzz33kJ+fj8lkYu7cuVitVubNm8frr7+O2WwmLS2Nhx9+mDVr1vCTn/wEg8GA2Wzmueee64RWCiGECGcSzq3YtGlTYD45OZlVq1a1Wq6mpobq6upWtw0YMIDNmzcDYLPZ+Nvf/taizEMPPcRDDz3UZN3ll1/O5ZdffqZVF0II0QPINWchhBAizEjP+WvasmULM2fObLLOarXy+eefh6hGQgghujsJ569p+PDh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\n",
      "text/plain": [
       "<Figure size 576x360 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "def plot_learning_curves(history):\n",
    "    pd.DataFrame(history.history).plot(figsize=(8, 5))\n",
    "    plt.grid(True)\n",
    "    plt.gca().set_ylim(0, 1)\n",
    "    plt.show()\n",
    "\n",
    "plot_learning_curves(history)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "10000/10000 [==============================] - 1s 98us/sample - loss: 0.4305 - accuracy: 0.8442\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[0.4304699492454529, 0.8442]"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model.evaluate(x_test_scaled, y_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
